package thread;

import java.sql.SQLOutput;

/**
 * 线程并发安全问题
 * 1.同步块；
 *      synchronized（同步监事的对象）{
 *
 *      }
 */
public class SyncDemo1 {
    public static void main(String[] args) {
        Shop shop = new Shop();
        Thread t1 = new Thread("王克晶"){
            public void run(){
                shop.buy();
            }
        };

        Thread t2 = new Thread("范传奇"){
            public void run(){
                shop.buy();
            }
        };

       /*
       重写方法与调用方法参数相同时，例如：run（）和buy（）或者run（String str）和buy（abc）
        Thread t1 = new Thread(shop::buy);  //方法引用
        Thread t2 = new Thread(shop::buy);
        */

        t1.start();
        t2.start();


        /*
        Shop shop1 = new Shop();
        Shop shop2 = new Shop();
        Thread t1 = new Thread("王克晶"){
            public void run(){
                shop1.buy();
            }
        };

        Thread t2 = new Thread("范传奇"){
            public void run(){
                shop2.buy();
            }
        };

        Thread t1 = new Thread(shop1::buy);
        Thread t2 = new Thread(shop2::buy);
        t1.start();
        t2.start();
        */
    }
}


class Shop{
    //public synchronized void buy(){  //在方法上同步监视（加锁）,范围比较大同步监视对象只能是this
    public void buy(){
        try {
            Thread t = Thread.currentThread();  //获取当前线程
            System.out.println(t.getName()+"正在挑衣服");
            Thread.sleep(3000);

            //  synchronized (123){  //编译错误，同步监视器对象一定是引用类型
            //  synchronized (new Object()){  //永远不能用实例化的对象作为同步监视器对象
            //  synchronized ("abc"){  //虽然可以锁上，但abc并不是合适的对象（在不同店试衣服时，试衣服时就会被锁，其他店的人不能试衣服，不合理）
            synchronized (this){  //this为锁对象，锁的是当前shop对象，只要是同个对象，就一定会被锁住
                System.out.println(t.getName()+"正在试衣服");
                Thread.sleep(3000);
            }

            System.out.println(t.getName()+"结账离开...");
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}